package com.ruoyi.websocket.service.impl;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.websocket.domain.DTO.WeChatMessageDTO;
import com.ruoyi.websocket.domain.DTO.WeChatTextDTO;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;


import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class WxService {

    @Autowired
    private WebClient webClient;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedissonClient redissonClient;

    private static final Logger logger = LoggerFactory.getLogger(WxService.class);

    //企业微信所需凭证
    private static final String corpid = "xxx";
    private static final String corpsecret = "xxx";


    private String getAccessTokenByApi(){
        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret=" + corpsecret;
        Map<String, Object> response = webClient.get()
                .uri(url)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
                .block();

        if (response == null || !response.containsKey("access_token")) {
            throw new RuntimeException("获取 access_token 失败：" + response);
        }
        return response.get("access_token").toString();
    }

    public String getAccessTokenByRedis() {
        //从redis中获取wx_access_token
        Object cacheObject = redisCache.getCacheObject("wx_access_token");
        //如果存在，直接返回access_token
        if(cacheObject != null){
            return cacheObject.toString();
        }
        //如果不存在，获取分布式锁
        RLock lock = redissonClient.getLock("wx_access_token_lock");
        //默认未上锁
        boolean locked = false;
        try {
            //尝试获取锁，最多等待3秒，上锁后10秒自动释放
            locked = lock.tryLock(3,10, TimeUnit.SECONDS);
            //如果获取到锁，再次从redis中获取access_token,防止在上锁期间，其他线程已经获取到锁并更新了access_token。
            if (locked) {
                cacheObject = redisCache.getCacheObject("wx_access_token");
                if(cacheObject != null){
                    return cacheObject.toString();
                }
                String accessToken = getAccessTokenByApi();
                //企业微信接口的返回值access_token有效期为7200秒，这里设置为7000秒，防止临界值过期问题。
                //将access_token存入redis，有效期7000秒。
                redisCache.setCacheObject("wx_access_token", accessToken,7000, TimeUnit.SECONDS);
                return accessToken;
            }else{
                //未取到锁
                throw new RuntimeException("获取 access_token 超时，请稍后再试");
            }
        }catch (Exception e){
            throw new RuntimeException("Redisson 锁被中断", e);
        }finally {
            if(locked && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    public Map<String,Object> pushMessage(WeChatMessageDTO weChatMessageDTO){
        String accessToken = getAccessTokenByRedis();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="+accessToken;

        return webClient.post()
                .uri(url)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(weChatMessageDTO)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
                .block(); // 阻塞获取响应（适用于同步调用场景）
    }

    /**
     * 推送企业微信通知
     */
    public void sendWeChatNotification(String title, String content, String receiverWxId) {
        try {
            WeChatTextDTO textDTO = new WeChatTextDTO();
            textDTO.setTitle(title);
            textDTO.setDescription(content);
            textDTO.setUrl("https://www.baidu.com");
            textDTO.setBtntxt("点击查看");

            WeChatMessageDTO messageDTO = new WeChatMessageDTO();
            messageDTO.setTouser(receiverWxId);
            messageDTO.setMsgtype("textcard");
            messageDTO.setAgentid(1000002);
            messageDTO.setTextcard(textDTO);

            Map<String, Object> result = pushMessage(messageDTO);
            logger.info("企业微信推送结果: {}", result);
        } catch (Exception e) {
            logger.error("企业微信推送失败", e);
        }
    }



}
